package cc.vv.lkimagecomponent2.glideLib;

import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;

import com.bumptech.glide.GenericTransitionOptions;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.TransitionOptions;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.CenterInside;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.bumptech.glide.load.resource.bitmap.FitCenter;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.request.transition.ViewPropertyTransition;

import java.util.ArrayList;

import cc.vv.lkimagecomponent2.LKImage;
import cc.vv.lkimagecomponent2.loaderplugin.TargetViewCallback;
import cc.vv.lkimagecomponent2.initplugin.InitConfig;
import cc.vv.lkimagecomponent2.lib.IEngine;
import cc.vv.lkimagecomponent2.lib.mode.AnimationMode;
import cc.vv.lkimagecomponent2.lib.mode.DiskCacheMode;
import cc.vv.lkimagecomponent2.loaderplugin.LoadConfig;
import cc.vv.lkimagecomponent2.loaderplugin.util.ImageUtil;
import cc.vv.lklibrary.log.LogOperate;
import jp.wasabeef.glide.transformations.BlurTransformation;
import jp.wasabeef.glide.transformations.ColorFilterTransformation;
import jp.wasabeef.glide.transformations.CropSquareTransformation;
import jp.wasabeef.glide.transformations.GrayscaleTransformation;
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
import jp.wasabeef.glide.transformations.gpu.BrightnessFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.ContrastFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.InvertFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.PixelationFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.SepiaFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.SketchFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.SwirlFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.ToonFilterTransformation;
import jp.wasabeef.glide.transformations.gpu.VignetteFilterTransformation;

/**
 * Glide 库
 *
 * @author dupeng dupeng@vv.cc
 * @date 2018/3/14
 */

public class GlideEngine implements IEngine {
    private static GlideEngine instance;

    private InitConfig initConfig;

    public static GlideEngine getInstance() {
        if (instance == null) {
            synchronized (GlideEngine.class) {
                if (instance == null) {
                    instance = new GlideEngine();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化.glide 的初始化都放在了MainGlideModule类中.
     *
     * @param config
     */
    @Override
    public void init(InitConfig config) {
        this.initConfig = config;
    }

    /**
     * 清空所有缓存.内存,sd.
     */
    @Override
    public void clearAllMemoryCaches() {
        clearMemory();
        clearDiskCache();
    }

    /**
     * 暂停所有图片请求
     */
    @Override
    public void pauseRequests() {
        Glide.with(LKImage.getContext()).pauseRequestsRecursive();
    }

    /**
     * 开始所有图片请求
     */
    @Override
    public void resumeRequests() {
        Glide.with(LKImage.getContext()).resumeRequestsRecursive();
    }

    /**
     * 清空view中的图片缓存
     *
     * @param view
     */
    @Override
    public void clearMemoryCache(View view) {
        Glide.with(LKImage.getContext()).clear(view);
    }

    /**
     * 清空外存图片缓存
     */
    @Override
    public void clearDiskCache() {
        //阻塞方法
        Glide.get(initConfig.getContext()).clearDiskCache();
    }

    /**
     * 清空运存中的图片缓存
     */
    @Override
    public void clearMemory() {
        Glide.get(initConfig.getContext()).clearMemory();
    }

    @Override
    public void load(final LoadConfig config) {
        if (config == null || config.getContext() == null) {
            LogOperate.eT(LKImage.TAG, "图片请求参数为空,或context为空！");
            return;
        }

        //1.初始化requestManager
        final RequestManager requestManager = GlideApp.with(config.getContext());

        //2.设置请求类型,gif还是bitmap...,以及调用load()方法,返回requestBuilder类
        RequestBuilder builder = generateRequestBuilder(requestManager, config);
        if (builder == null) {
            LogOperate.eT(LKImage.TAG, "图片请求失败,RequestBuild为空!");
            return;
        }

        //3.设置请求参数.
        initOptions(config, builder);

        //4.设置到target
        Target target = null;
        if (config.isAsBitmap()) {
            target = generateBitmapTarget(config);
        } else {
            //drawable 或gif
            target = generateDrawableGifTarget(config);
        }
        if (target != null) {
            builder.into(target);
        } else {
            LogOperate.eT(LKImage.TAG, "图片加载,Target生成失败,为空!");
        }
    }

    /**
     * 初始化请求参数
     *
     * @param config
     * @param builder
     */
    private void initOptions(LoadConfig config, RequestBuilder builder) {
        //1.设置转化option
        setThumbnail(config, builder);
        setCrossFade(config, builder);
        setAnimator(config, builder);


        //2.设置请求option
        RequestOptions requestOptions = new RequestOptions();
        setDiskCacheStrategy(config, requestOptions);
        setShapeModeAndBlur(config, requestOptions);
        setOverrideWH(config, requestOptions);
        setPlaceHolder(config, requestOptions);
        setErrorRes(config, requestOptions);
        setIsAnimator(config, requestOptions);
        setPriority(config, requestOptions);
        builder.apply(requestOptions);

    }

    /**
     * 生成drawable类型的target
     *
     * @param config
     */
    private Target generateDrawableGifTarget(final LoadConfig config) {
        Target target = null;
        if (config.getTarget() instanceof ImageView) {
            target = new ImageViewTarget<Drawable>((ImageView) config.getTarget()) {
                @Override
                protected void setResource(@Nullable Drawable resource) {
                    Drawable drawable = generateDrawable(resource, config);
                    ImageView iv = (ImageView) config.getTarget();
                    iv.setImageDrawable(drawable);
                }
            };
        } else {
            final TargetViewCallback targetViewCallback = config.getTargetViewCallback();
            if (targetViewCallback != null) {
                target = new SimpleTarget<Drawable>() {

                    @Override
                    public void onLoadStarted(Drawable placeholder) {
                        super.onLoadStarted(placeholder);
                        TargetViewCallback targetViewCallback = config.getTargetViewCallback();
                        if (targetViewCallback != null) {
                            targetViewCallback.onStart(placeholder);
                        }
                    }

                    @Override
                    public void onLoadFailed(Drawable errorDrawable) {
                        super.onLoadFailed(errorDrawable);
                        TargetViewCallback targetViewCallback = config.getTargetViewCallback();
                        if (targetViewCallback != null) {
                            targetViewCallback.onFail(errorDrawable);
                        }
                    }

                    @Override
                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                        Drawable drawable = generateDrawable(resource, config);
                        if (targetViewCallback != null) {
                            targetViewCallback.onSuccess(drawable);
                        }
                    }
                };
            }
        }
        return target;
    }

    /**
     * 如果resource
     *
     * @param resource
     * @param config
     * @return
     */
    private Drawable generateDrawable(Drawable resource, LoadConfig config) {
        try {
            if (resource instanceof Animatable) {
                //加载的为gif图
                GifDrawable gifDrawable = (GifDrawable) resource;
                if (-1 == config.getGifRepeatCount()) {
                    //一直执行
                    gifDrawable.start();
                    gifDrawable.setLoopCount(GifDrawable.LOOP_FOREVER);
                } else if (0 == config.getGifRepeatCount()) {
                    //不执行
                    gifDrawable.stop();
                } else {
                    gifDrawable.start();
                    gifDrawable.setLoopCount(config.getGifRepeatCount());
                }
            } else {
                //加载为普通tup
            }
        } catch (Exception e) {
            LogOperate.eT(LKImage.TAG, "图片加载 GifDrawable 设置失败,有可能是gifRepeatCount小于-1了!", e);
        }
        return resource;
    }

    /**
     * 生成bitmap 的target
     *
     * @param config
     * @return
     */
    private Target generateBitmapTarget(final LoadConfig config) {
        Target target = new SimpleTarget<Bitmap>() {
            @Override
            public void onResourceReady(@NonNull final Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                if (config.getBitmapListener() != null) {
                    ImageUtil.getMainHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            config.getBitmapListener().onSuccess(resource);
                        }
                    });
                }
            }

            @Override
            public void onLoadStarted(@Nullable final Drawable placeholder) {
                super.onLoadStarted(placeholder);
                if (config.getBitmapListener() != null) {
                    ImageUtil.getMainHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            config.getBitmapListener().onStart(placeholder);
                        }
                    });
                }
            }

            @Override
            public void onLoadFailed(@Nullable final Drawable errorDrawable) {
                super.onLoadFailed(errorDrawable);
                if (config.getBitmapListener() != null) {
                    ImageUtil.getMainHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            config.getBitmapListener().onFail(errorDrawable);
                        }
                    });
                }
            }
        };
        return target;
    }

    /**
     * 设置磁盘缓存模式
     *
     * @param config
     * @param requestOptions
     */
    private void setDiskCacheStrategy(LoadConfig config, RequestOptions requestOptions) {
        if (config.getDiskCacheStrategy() != null) {
            requestOptions.diskCacheStrategy(getDiskStrategy(config.getDiskCacheStrategy()));
            if (config.isGif()) {
                //防止gif卡顿
                requestOptions.diskCacheStrategy(DiskCacheStrategy.RESOURCE);
            }
        }
    }

    /**
     * 设置placeholder
     *
     * @param config
     * @param requestOptions
     */
    private void setPlaceHolder(LoadConfig config, RequestOptions requestOptions) {
        if (config.getPlaceHolderDrawable() != null) {
            requestOptions.placeholder(config.getPlaceHolderDrawable());
        } else if (config.getPlaceHolderResId() > 0) {
            requestOptions.placeholder(config.getPlaceHolderResId());
        }
    }

    /**
     * 设置是否动画
     *
     * @param config
     * @param requestOptions
     */
    private void setIsAnimator(LoadConfig config, RequestOptions requestOptions) {
        if (!config.isAnim()) {
            requestOptions.dontAnimate();
//            requestOptions.dontTransform();
        }
    }

    /**
     * 设置请求类型(bitmap,drawable...),调用load()方法
     *
     * @param requestManager
     * @param config
     * @return
     */
    private RequestBuilder generateRequestBuilder(RequestManager requestManager, LoadConfig config) {
        RequestBuilder builder;
        if (config.isAsBitmap()) {
            builder = requestManager.asBitmap();
        } else if (config.isGif()) {
            builder = requestManager.asGif();
        } else {
            builder = requestManager.asDrawable();
        }
        loadDiffType(config, builder);

        return builder;
    }

    /**
     * 设置渐显动画
     *
     * @param config
     * @param requestBuilder
     */
    private void setCrossFade(LoadConfig config, RequestBuilder requestBuilder) {
        if (config.isCrossFade()) {
            TransitionOptions transitionOptions = null;
            if (config.isAsBitmap()) {
                if (config.getCrossFadeDuration() > 0) {
                    transitionOptions = new BitmapTransitionOptions().crossFade(config.getCrossFadeDuration());
                } else {
                    transitionOptions = new BitmapTransitionOptions().crossFade();
                }
            } else {
                if (config.getCrossFadeDuration() > 0) {
                    transitionOptions = new DrawableTransitionOptions().crossFade(config.getCrossFadeDuration());
                } else {
                    transitionOptions = new DrawableTransitionOptions().crossFade();
                }
            }
            requestBuilder.transition(transitionOptions);
        }
    }

    /**
     * 设置紧急程度
     *
     * @param config
     * @param request
     */
    private void setPriority(LoadConfig config, RequestOptions request) {
        switch (config.getPriority()) {
            case PRIORITY_LOW:
                request.priority(Priority.LOW);
                break;
            case PRIORITY_NORMAL:
                request.priority(Priority.NORMAL);
                break;
            case PRIORITY_HIGH:
                request.priority(Priority.HIGH);
                break;
            case PRIORITY_IMMEDIATE:
                request.priority(Priority.IMMEDIATE);
                break;
            default:
                request.priority(Priority.IMMEDIATE);
                break;
        }
    }

    /**
     * 设置动画
     *
     * @param config
     * @param requestBuilder
     */
    private void setAnimator(final LoadConfig config, RequestBuilder requestBuilder) {
        if (config.getAnimationType() == null) {
            return;
        }
        if (config.getAnimationType() == AnimationMode.ANIMATIONID) {
            requestBuilder.transition(new GenericTransitionOptions().transition(config.getAnimationId()));
        } else if (config.getAnimationType() == AnimationMode.ANIMATION) {
            requestBuilder.transition(new GenericTransitionOptions().transition(new ViewPropertyTransition.Animator() {
                @Override
                public void animate(View view) {
                    if (view != null) {
                        view.startAnimation(config.getAnimation());
                    }
                }
            }));
        }
    }

    /**
     * 设置图片加载的分辨
     *
     * @param config
     * @param request
     */
    private void setOverrideWH(LoadConfig config, RequestOptions request) {
        if (config.getoWidth() != 0 && config.getoHeight() != 0) {
            request.override(config.getoWidth(), config.getoHeight());
        }
    }

    /**
     * 设置缩略图
     *
     * @param config
     * @param requestBuilder
     */
    private void setThumbnail(LoadConfig config, RequestBuilder requestBuilder) {
        //设置缩略图
        if (config.getThumbnail() != 0) {
            requestBuilder.thumbnail(config.getThumbnail());
        }
    }

    /**
     * 设置特效及 图片形状
     *
     * @param config
     * @param requestOptions
     */
    private void setShapeModeAndBlur(LoadConfig config, RequestOptions requestOptions) {
        ArrayList<Transformation<Bitmap>> transformations = new ArrayList<>();
        //设置特效
        if (config.isNeedBlur()) {
            transformations.add(new BlurTransformation(config.getBlurRadius(), 10));
        }
        if (config.isNeedBrightness()) {
            transformations.add(new BrightnessFilterTransformation(config.getBrightnessLeve()));
        }
        if (config.isNeedGrayscale()) {
            transformations.add(new GrayscaleTransformation());
        }
        if (config.isNeedFilteColor()) {
            transformations.add(new ColorFilterTransformation(config.getFilteColor()));
        }
        if (config.isNeedSwirl()) {
            //旋涡效果
            transformations.add(new SwirlFilterTransformation(0.5f, 1.0f, new PointF(0.5f, 0.5f)));
        }
        if (config.isNeedToon()) {
            //油画
            transformations.add(new ToonFilterTransformation());
        }
        if (config.isNeedSepia()) {
            //墨画
            transformations.add(new SepiaFilterTransformation());
        }
        if (config.isNeedContrast()) {
            transformations.add(new ContrastFilterTransformation(config.getContrastLevel()));
        }
        if (config.isNeedInvert()) {
            //胶片
            transformations.add(new InvertFilterTransformation());
        }
        if (config.isNeedPixelation()) {
            //像素化
            transformations.add(new PixelationFilterTransformation(config.getPixelationLevel()));
        }
        if (config.isNeedSketch()) {
            //素描
            transformations.add(new SketchFilterTransformation());
        }
        if (config.isNeedVignette()) {
            //晕映
            transformations.add(new VignetteFilterTransformation(new PointF(0.5f, 0.5f),
                    new float[]{0.0f, 0.0f, 0.0f}, 0f, 0.75f));
        }

        //设置scaleType
        switch (config.getScaleMode()) {
            case CENTER_CROP:
                transformations.add(new CenterCrop());
                break;
            case FIT_CENTER:
                transformations.add(new FitCenter());
                break;
            case CENTER_INSIDE:
                transformations.add(new CenterInside());
                break;
            default:
                transformations.add(new FitCenter());
                break;
        }

        //设置图形
        switch (config.getShapeMode()) {
            case RECT:
                break;
            case RECT_ROUND:
                transformations.add(new RoundedCornersTransformation
                        (config.getRectRoundRadius(), 0, RoundedCornersTransformation.CornerType.ALL));
                break;
            case OVAL:
                transformations.add(new CircleCrop());
                break;
            case SQUARE:
                transformations.add(new CropSquareTransformation());
                break;
            default:
                break;
        }

        try {
            if (transformations != null && transformations.size() > 0) {
                Transformation[] transformations1 = new Transformation[transformations.size()];
                for (int i = 0; i < transformations.size(); i++) {
                    transformations1[i] = transformations.get(i);
                }
                requestOptions.transforms(transformations1);
            }
        } catch (ClassCastException e) {
            LogOperate.e(e);
        }
    }

    /**
     * 调用load方法
     *
     * @param config
     * @param requestBuilder
     */
    private void loadDiffType(LoadConfig config, RequestBuilder requestBuilder) {
        Uri uri = ImageUtil.buildUriByType(config);
        if (uri != null) {
            requestBuilder.load(uri);
            LogOperate.iT(LKImage.TAG, "图片请求：" + uri.toString());
            return;
        }

        if (!TextUtils.isEmpty(config.getUrl())) {
            requestBuilder.load(config.getUrl());
            LogOperate.iT(LKImage.TAG, "图片请求：" + config.getUrl());
        } else if (config.getFile() != null) {
            requestBuilder.load(config.getFile());
            LogOperate.iT(LKImage.TAG, "图片请求文件：" + config.getFile().getAbsolutePath());
        } else {
            requestBuilder.load("");
            LogOperate.wT(LKImage.TAG, "图片请求失败，找不到对应图片资源！");
        }
    }

    /**
     * 磁盘缓存模式
     *
     * @param diskcacheMode
     * @return
     */
    private DiskCacheStrategy getDiskStrategy(DiskCacheMode diskcacheMode) {
        if (diskcacheMode == null) {
            return DiskCacheStrategy.AUTOMATIC;
        }

        DiskCacheStrategy strategy;
        switch (diskcacheMode) {
            case ALL:
                strategy = DiskCacheStrategy.ALL;
                break;
            case NONE:
                strategy = DiskCacheStrategy.NONE;
                break;
            case RESOURCE:
                strategy = DiskCacheStrategy.RESOURCE;
                break;
            case AUTOMATIC:
                strategy = DiskCacheStrategy.AUTOMATIC;
                break;
            default:
                strategy = DiskCacheStrategy.AUTOMATIC;
        }
        return strategy;
    }

    /**
     * 设置错误占位图
     *
     * @param config
     * @param request
     */
    private void setErrorRes(LoadConfig config, RequestOptions request) {
        if (config.getErrorDrawable() != null) {
            request.error(config.getErrorDrawable());
        } else if (config.getErrorResId() > 0) {
            request.error(config.getErrorResId());
        }
    }

}
